package com.example.java.newFeature.thread;

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadFactory;

public class VirtualCompletableFutureDemo {
    public static void main(String[] args) {
        // 创建一个虚拟线程执行器，为每个任务创建一个新的虚拟 Thread，该 newVirtualThreadPerTaskExecutor 方法内部如下：
        /*
         *   ThreadFactory factory = Thread.ofVirtual().factory();
         *   return newThreadPerTaskExecutor(factory);
         * 因此，默认的虚拟线程是没有名称的，可以通过 Thread.ofVirtual().name("my-virtual-thread") 来设置名称。
        */
        var executor = Executors.newVirtualThreadPerTaskExecutor();
        executor.submit(() -> {
            String threadName = Thread.currentThread().getName();
            System.out.println("executor 1 - Running in: " + threadName);
        });

        // 常规的线程池，线程池中每个任务都在 Java 线程池中执行。
        // 自定义线程工厂，线程工厂是执行器中真正用来创建新线程的。线程执行器在外包装了一层
        ThreadFactory factory = Thread.ofVirtual().name("my-virtual-thread", 1).factory();
        var executor2 = Executors.newThreadPerTaskExecutor(factory);
        executor2.submit(() -> {
            String threadName = Thread.currentThread().getName();
            System.out.println("executor 2 - Running in: " + threadName);
        });


        // 使用 CompletableFuture 与虚拟线程
        CompletableFuture.supplyAsync(() -> {
                    // 模拟一些计算
                    System.out.println("Task 1 - Running in: " + Thread.currentThread().getName());
                    return "Hello";
                }, executor)
                .thenApplyAsync(result -> {
                    // 处理结果
                    System.out.println("Task 2 - Running in: " + Thread.currentThread().getName());
                    return result + ", World!";
                }, executor)
                .thenAcceptAsync(System.out::println, executor);

        // 确保主线程等待异步任务完成
        try {
            Thread.sleep(1000);  // 睡眠一段时间
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }


        Thread virtualThread1 = Thread.ofVirtual().name("Task 1").unstarted(() -> {
            System.out.println("Task 1 - Running in: " + Thread.currentThread().getName());
        });

        Thread virtualThread2 = Thread.ofVirtual().name("Task 2").unstarted(() -> {
            System.out.println("Task 2 - Running in: " + Thread.currentThread().getName());
        });

        virtualThread1.start();
        virtualThread2.start();
        // 确保主线程等待虚拟线程完成
        try {
            virtualThread1.join();
            virtualThread2.join();
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
    }
}

/*
CompletableFuture 使用虚拟线程的注意点：
1. CompletableFuture 中的所有任务都是在虚拟线程中执行的，而不是在 Java 线程池中。因此将执行器传递给它们。这样，所有的操作都将在虚拟线程中进行。
2. 一致性：所有的操作都运行在相同的执行器中，确保没有线程上下文切换的问题，更加一致。
3. 性能：虚拟线程的轻量级特性在提高并发能力的同时，减少了上下文切换的开销。
*/